package com.xlh.enums.courseTest;

import cn.hutool.core.date.DateTime;
import cn.hutool.core.util.RandomUtil;
import com.alibaba.fastjson.JSONArray;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.xlh.dto.course.CourseBasicDTO;
import com.xlh.dto.courseTest.AnswerSheetTypeDTO;
import com.xlh.dto.courseTest.TypeReadingDTO;
import com.xlh.dto.courseTest.check.CheckDTO;
import com.xlh.dto.courseTest.check.ExperimentReportDTO;
import com.xlh.dto.courseTest.practice.SubmitDTO;
import com.xlh.dto.user.UserInfoDTO;
import com.xlh.enums.LocalResourcesEnum;
import com.xlh.exception.common.GlobalException;
import com.xlh.param.check.CheckSubmitParam;
import com.xlh.param.courseTest.TypeReadingParam;
import com.xlh.pojo.course.ChapterBasic;
import com.xlh.pojo.courseTest.ExperimentReport;
import com.xlh.pojo.courseTest.Practice;
import com.xlh.pojo.user.UserClass;
import com.xlh.service.MdHtmlFileService;
import com.xlh.service.course.ChapterService;
import com.xlh.service.course.CourseService;
import com.xlh.service.courseTest.ExperimentService;
import com.xlh.service.courseTest.PracticeService;
import com.xlh.service.courseTest.QuestionRepositoryDetailsService;
import com.xlh.service.courseTest.QuestionRepositoryService;
import com.xlh.service.user.UserService;
import com.xlh.util.SpringContextUtil;
import lombok.AllArgsConstructor;
import lombok.Getter;
import org.apache.commons.collections.CollectionUtils;

import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * @author zhr 2019/4/3
 */
@Getter
@AllArgsConstructor
public enum CheckEnum {
    PRACTICE(1, "随堂练习") {
        @Override
        public SubmitDTO readDetails(Long id, Long chapterId, List<UserClass> userClassList, Long courseId) {
            List<Long> userClassIdList = userClassList.stream().map(UserClass::getId).collect(Collectors.toList());
            Map<Long, Long> idUserIdMap = userClassList.stream().collect(Collectors.toMap(UserClass::getId, UserClass::getUserId));

            Practice practice = practiceService.selectByPrimaryKey(id);
            if (practice == null) {
                throw new GlobalException("当前随堂练习不存在，请关闭页面，重新打开");
            }
            List<Practice> practiceList = practiceService.selectByChapterIdStudentIds(chapterId, userClassIdList);
            ChapterBasic chapter = chapterService.getChapterInfo(chapterId);
            CourseBasicDTO course = courseService.getCourse(courseId);

            Long userId = idUserIdMap.get(practice.getStudentId());
            if (userId == null) {
                throw new GlobalException("用户不存在");
            }
            UserInfoDTO user = userService.getUserInfo(userId, null);
            List<TypeReadingDTO> readingList = practiceService.getDetails(practice);
            int score = practice.getScore();

            // 将归档文件转为映射地址
            if (practice.getPdf() != null) {
                practice.setPdf(LocalResourcesEnum.PDF.getMappingUrl(practice.getPdf()));
            }

            return new SubmitDTO(practice, practiceList, chapter, course, user, readingList, score);
        }

        @Override
        public SubmitDTO read(Long id, CheckSubmitParam param) {
            List<TypeReadingParam> typeScoreList = param.getReadingList();
            if (CollectionUtils.isEmpty(typeScoreList)) {
                throw new GlobalException("请打分后再进行提交");
            }
            // 查询答题卡信息
            Practice practice = practiceService.selectByPrimaryKey(id);

            // 提取答题卡详情，并提取为题目id-答题卡映射
            List<AnswerSheetTypeDTO> answerSheetTypeList = JSONArray.parseArray(practice.getContent(), AnswerSheetTypeDTO.class);

            // 将得分信息封装至答题卡中
            Map<Integer, Integer> typeScoreMap = typeScoreList.stream().collect(
                    Collectors.toMap(TypeReadingParam::getType, TypeReadingParam::getTotalScore)
            );
            // 封装题目得分
            answerSheetTypeList.forEach(dto -> dto.setScore(typeScoreMap.get(dto.getType())));

            // 归档pdf名称
            String fileName = practice.getPdf() == null ? RandomUtil.simpleUUID() + ".pdf" : practice.getPdf();

            practice.setScore(param.getScore());
            practice.setContent(JSONArray.toJSONString(answerSheetTypeList));
            practice.setUpdateTime(DateTime.now());
            practice.setCheck(true);
            practice.setPdf(fileName);
            practice.setCheckResult(param.getCheckResult());
            practice.setTemplateId(param.getTemplateId());

            practiceService.updateByPrimaryKey(practice);
            practiceService.updatePDF(fileName, param);

            return new SubmitDTO();
        }
    },
    EXPERIMENT(2, "实验") {
        @Override
        public ExperimentReportDTO readDetails(Long id, Long chapterId, List<UserClass> userClassList, Long courseId) {
            ExperimentReportDTO result = new ExperimentReportDTO();

            List<Long> userClassIdList = userClassList.stream().map(UserClass::getId).collect(Collectors.toList());
            Map<Long, Long> idUserIdMap = userClassList.stream().collect(Collectors.toMap(UserClass::getId, UserClass::getUserId));

            ExperimentReport report = experimentService.selectByPrimaryKey(id);
            List<ExperimentReport> reportList = experimentService.selectSubmitByChapterIdStudentIds(chapterId, userClassIdList);
            ChapterBasic chapter = chapterService.getChapterInfo(chapterId);

            Long userId = idUserIdMap.get(report.getStudentId());
            if (userId == null) {
                throw new GlobalException("用户不存在");
            }

            CourseBasicDTO course = courseService.getCourse(courseId);

            UserInfoDTO user = userService.getUserInfo(userId, null);

            // 将归档文件转为映射地址
            if (report.getReportPdf() != null) {
                report.setReportPdf(LocalResourcesEnum.PDF.getMappingUrl(report.getReportPdf()));
            }
            result.setChapterName(chapter.getName());
            result.setCourseName(course.getName());
            result.setUserName(user.getName());
            result.setUserNumber(user.getUserNumber());
            result.setPdf(report.getReportPdf());
            if (result.getPdf() != null) {
                result.setPdfName(result.getUserNumber() + "_" + result.getUserName() + ".pdf");
            }
            result.setCheckResult(report.getCheckResult());
            result.setTemplateId(report.getTemplateId());


            // 设置批阅id以及前一id后一id
            experimentService.setPoint(result, id, reportList);
            // 设置批阅的详情, 克隆一个新的reportList防止reportList被操作干扰
            experimentService.setDetails(result, report, Lists.newArrayList(reportList), courseId);

            return result;
        }

        @Override
        public CheckDTO read(Long id, CheckSubmitParam param) {
            ExperimentReport report = experimentService.selectByPrimaryKey(id);
            String fileName = report.getReportPdf() == null ? RandomUtil.simpleUUID() + ".pdf" : report.getReportPdf();

            // 查询答题卡信息
            ExperimentReport experimentReport = experimentService.selectByPrimaryKey(id);
            experimentReport.setCheck(true);
            experimentReport.setScore(param.getScore());
            experimentReport.setUpdateTime(DateTime.now());
            experimentReport.setCheckResult(param.getCheckResult());
            experimentReport.setReportPdf(fileName);
            experimentReport.setTemplateId(param.getTemplateId());

            experimentService.updateByPrimaryKey(experimentReport);
            experimentService.updatePDF(fileName, param);

            return new ExperimentReportDTO();
        }
    };

    private final Integer type;
    private final String message;

    private static PracticeService practiceService = SpringContextUtil.getBean(PracticeService.class);
    private static QuestionRepositoryService repositoryService = SpringContextUtil.getBean(QuestionRepositoryService.class);
    private static MdHtmlFileService mdHtmlFileService = SpringContextUtil.getBean(MdHtmlFileService.class);
    private static QuestionRepositoryDetailsService detailsService = SpringContextUtil.getBean(QuestionRepositoryDetailsService.class);
    private static ExperimentService experimentService = SpringContextUtil.getBean(ExperimentService.class);
    private static UserService userService = SpringContextUtil.getBean(UserService.class);
    private static CourseService courseService = SpringContextUtil.getBean(CourseService.class);
    private static ChapterService chapterService = SpringContextUtil.getBean(ChapterService.class);

    private static Map<Integer, CheckEnum> typeMap = Maps.newHashMap();

    static {
        for (CheckEnum en : CheckEnum.values()) {
            typeMap.put(en.getType(), en);
        }
    }

    public static CheckEnum forType(Integer type) {
        return typeMap.get(type);
    }

    public abstract CheckDTO readDetails(Long id, Long chapterId, List<UserClass> userClassList, Long courseId);

    public abstract CheckDTO read(Long id, CheckSubmitParam param);

}
